#ifndef __network_kenny_ojfwoeeif9w23__
#define __network_kenny_ojfwoeeif9w23__


#if defined( _WIN32 ) || defined( _WIN64 )
#  include <winsock2.h>
#  include <WS2tcpip.h>
#else
#  include <poll.h>
#  include <errno.h>
#  include <fcntl.h>
#  include <unistd.h>
#  include <sys/socket.h>
#  include <sys/select.h>
#  include <netdb.h>
#  include <arpa/inet.h>
#  include <netinet/tcp.h>
#  include <netinet/udp.h>
#endif

#include <unordered_map>

#include <hude/base/base_type.hpp>
#include <hude/base/hex.hpp>
#include <hude/base/block_queue.hpp>
#include <hude/aio/context.hpp>

#ifdef DEBUG_NETWORK
#   define _log_war     llog_war
#   define _log_nte     llog_nte
#   define _log_dug     llog_dug
#   define _log_tra     llog_tra
#else
#   define _log_war( ... )
#   define _log_nte( ... )
#   define _log_dug( ... )
#   define _log_tra( ... )
#endif

namespace dnet
{
#ifndef    INVALID_SOCKET
#  define INVALID_SOCKET ( -1 )
#endif

#if defined( _WIN32 ) || defined( _WIN64 )
#  ifndef SHUT_RD
#    define SHUT_RD SD_RECEIVE
#  endif
#  ifndef SHUT_WR
#    define SHUT_WR SD_SEND
#  endif
#  ifndef SHUT_RDWR
#    define SHUT_RDWR SD_BOTH
#  endif
#endif

#if defined( _WIN32 ) || defined( _WIN64 )
typedef SOCKET socket_t;
#else
typedef int    socket_t;
#endif

#if defined( _WIN32 ) || defined( _WIN64 )
#  ifndef ssize_t
#    define ssize_t int
#  endif
#  ifndef socklen_t
#    define socklen_t int
#  endif
#  ifndef nfds_t
#    define nfds_t ULONG
#  endif
#endif

#if defined( _WIN32 ) || defined( _WIN64 )
#  define ERR_SOCK_WAITTING 10035
#  define SHUTDOWN_RDWD  SD_BOTH
#else
#  define ERR_SOCK_WAITTING EINPROGRESS
#  define SHUTDOWN_RDWD  SHUT_RDWR
#endif

/**
 * @brief _socket_accept
 */

static __inline socket_t _socket_accept( socket_t s, struct sockaddr * addr, socklen_t * addrlen )
{
    return accept( s, addr, addrlen );
}

/**
 * @brief _socket_bind
 */

static __inline int _socket_bind( socket_t s, const struct sockaddr * addr, socklen_t addrlen )
{
    return bind( s, addr, addrlen );
}

/**
 * @brief _socket_close
 */

static __inline int _socket_close( socket_t s )
{
    #if defined( _WIN32 ) || defined( _WIN64 )

    return closesocket( s );

    #else

    return close( s );

    #endif
}

/**
 * @brief _socket_connect
 */

static __inline int _socket_connect( socket_t s, const struct sockaddr * addr, socklen_t addrlen )
{
    return connect( s, addr, addrlen );
}


/**
 * @brief _socket_get_error
 */

static __inline int _socket_get_error()
{
    #if defined( _WIN32 ) || defined( _WIN64 )

    return WSAGetLastError();

    #else

    return errno;

    #endif
}

/**
 * @brief _socket_getpeername
 */

static __inline int _socket_getpeername( socket_t s, struct sockaddr * addr, socklen_t * addrlen )
{
    return getpeername( s, addr, addrlen );
}

/**
 * @brief _socket_getsockname
 */

static __inline int _socket_getsockname( socket_t s, struct sockaddr * addr, socklen_t * addrlen )
{
    return getsockname( s, addr, addrlen );
}

/**
 * @brief _socket_getsockopt
 */

static __inline int _socket_getsockopt( socket_t s, int level, int optname, void * optval, socklen_t * optlen )
{
    #if defined( _WIN32 ) || defined( _WIN64 )

    return getsockopt( s, level, optname, ( char * )optval, optlen );

    #else

    return getsockopt( s, level, optname, optval, optlen );

    #endif
}

/**
 * @brief _socket_listen
 */

static __inline int _socket_listen( socket_t s, int backlog )
{
    return listen( s, backlog );
}

/**
 * @brief _socket_open
 */

static __inline socket_t _socket_open( int domain, int type, int protocol )
{
    return socket( domain, type, protocol );
}

/**
 * @brief _socket_poll
 */

static __inline int _socket_poll( struct pollfd * fds, nfds_t nfds, int timeout )
{
    #if defined( _WIN32 ) || defined( _WIN64 )

    return WSAPoll( fds, nfds, timeout );

    #else

    return poll( fds, nfds, timeout );

    #endif
}

/**
 * @brief _socket_recv
 */

static __inline ssize_t _socket_recv( socket_t s, void * buf, size_t buflen, int flags )
{
    #if defined( _WIN32 ) || defined( _WIN64 )

    return recv( s, ( char * )buf, ( int )buflen, flags );

    #else

    return recv( s, buf, buflen, flags );

    #endif
}

/**
 * @brief _socket_recvfrom
 */

static __inline ssize_t _socket_recvfrom( socket_t s, void * buf, size_t buflen, int flags, struct sockaddr * addr, socklen_t * addrlen )
{
    #if defined( _WIN32 ) || defined( _WIN64 )

    return recvfrom( s, ( char * )buf, ( int )buflen, flags, addr, addrlen );

    #else

    return recvfrom( s, buf, buflen, flags, addr, addrlen );

    #endif
}

/**
 * @brief _socket_select
 */

static __inline int _socket_select( int nfds, fd_set * readfds, fd_set * writefds, fd_set * errorfds, struct timeval * timeout )
{
    return select( nfds, readfds, writefds, errorfds, timeout );
}

/**
 * @brief _socket_send
 */

static __inline ssize_t _socket_send( socket_t s, const void * buf, size_t buflen, int flags )
{
    #if defined( _WIN32 ) || defined( _WIN64 )

    return send( s, ( const char * )buf, ( int )buflen, flags );

    #else

    return send( s, buf, buflen, flags );

    #endif
}

/**
 * @brief _socket_sendto
 */

static __inline ssize_t _socket_sendto( socket_t s, const void * buf, size_t buflen, int flags, const struct sockaddr * addr, socklen_t addrlen )
{
    #if defined( _WIN32 ) || defined( _WIN64 )

    return sendto( s, ( const char * )buf, ( int )buflen, flags, addr, addrlen );

    #else

    return sendto( s, buf, buflen, flags, addr, addrlen );

    #endif
}

/**
 * @brief _socket_setsockopt
 */

static __inline int _socket_setsockopt( socket_t s, int level, int optname, const void * optval, socklen_t optlen )
{
    #if defined( _WIN32 ) || defined( _WIN64 )

    return setsockopt( s, level, optname, ( const char * )optval, optlen );

    #else

    return setsockopt( s, level, optname, optval, optlen );

    #endif
}

/**
 * @brief _socket_shutdown
 */

static __inline int _socket_shutdown( socket_t s, int how )
{
    return shutdown( s, how );
}

/**
 * @brief _socket_set_non_block
 */

static __inline int _socket_set_non_block( socket_t s )
{
    #if defined( _WIN32 ) || defined( _WIN64 )

    u_long yes = 1;

    return ( SOCKET_ERROR == ioctlsocket( s, FIONBIO, &yes ) ) ? ( -1 ) : ( 0 );

    #else

    int flags;

    if ( -1 == ( flags = fcntl( s, F_GETFL ) ) )
    {
        return -1;
    }

    if ( -1 == fcntl( s, F_SETFL, flags | O_NONBLOCK ) )
    {
        return -1;
    }

    return 0;

    #endif
}

#if defined( _WIN32 ) || defined( _WIN64 )
#  undef ssize_t
#  undef socklen_t
#  undef nfds_t
#endif

} //namespace dnet
namespace dnet
{
    /*********************************************************************
     * @brief 地址类型标识定义
     */
    enum net_ver_t : uint16_t { emV4 = AF_INET, emV6 = AF_INET6 };

    /*********************************************************************
     * @brief 事件类型定义
     */
    using event_t = hude::aio::epoll_evt_t;

    /*********************************************************************
     * @brief 地址类型定义
     */
    template< net_ver_t _ver > struct _address_t {};

    template<> struct _address_t< emV4 > : public sockaddr_in 
    {
        using type_t = sockaddr_in;
        enum : std::size_t { emSIZE = sizeof( type_t ) };
    };

    template<> struct _address_t< emV6 > : public sockaddr_in6
    {
        using type_t = sockaddr_in6;
        enum : std::size_t { emSIZE = sizeof( type_t ) };
    };

    /*********************************************************************
     * @brief 协议无关的地址定义
     */
    struct address_t : sockaddr_storage
    {
        typedef sockaddr_storage type_t;
        enum { emSIZE = sizeof(type_t) };

        union sockaddr_all_t
        {
            struct sockaddr         sa;
            struct sockaddr_in      sa4;
            struct sockaddr_in6     sa6;
            struct sockaddr_storage sas;
        };
        
        void reset()
        {
            memset( this, 0, emSIZE );
        }

        // for socket bind:    int flags = AI_PASSIVE | AI_NUMERICHOST
        // for socket connect: int flags = 0
        static bool getaddrinfo( const char* host, const char* serv,
            std::function< bool( const struct addrinfo& ) > cb, int flags )
        {
            addrinfo hints, *paddrs;

            memset( &hints, 0, sizeof(hints) );

            hints.ai_family = AF_UNSPEC;
            hints.ai_socktype = SOCK_DGRAM;
            hints.ai_flags = flags;

            auto ret = ::getaddrinfo( host, serv, &hints, &paddrs );
            if( ret ) return false;
            
            for( auto p = paddrs; p != nullptr; p = p->ai_next )
            {
                if( ! cb( *p ) ) break;
            }

            freeaddrinfo( paddrs );

            return true;
        }

        static bool getnameinfo( const sockaddr_storage& addr, std::string& domain )
        {
            std::string host, serv;

            host.resize( NI_MAXHOST );
            serv.resize( NI_MAXSERV );

            auto ret = ::getnameinfo( (const sockaddr*)&addr, emSIZE, &(host[0]), NI_MAXHOST, &(serv[0]), NI_MAXSERV, 0 );
            if( ret ) return false;

            if( addr.ss_family == AF_INET6 )
            {
                domain.swap( hude::format_t( "[%s]:%s", host.c_str(), serv.c_str() ).str() );
            } else {
                domain.swap( hude::format_t( "%s:%s",   host.c_str(), serv.c_str() ).str() );
            }

            return true;
        }

        bool reset( const char* host, uint16_t port, int flag = 0 )
        {
            reset();

            auto cb = [=]( const addrinfo& addr )
            {
                if( addr.ai_family == AF_INET6 || addr.ai_family == AF_INET )
                {
                    auto ptr = static_cast< void* >( this );

                    memcpy( ptr, addr.ai_addr, addr.ai_addrlen );

                    return false;
                }

                return true;
            };

            return getaddrinfo( host, hude::format_t( "%hu", port ).c_str(), cb , flag );
        }

        bool reset( const sockaddr* addr, std::size_t size )
        {
            memcpy( this, addr, size );
            return true;
        }

        address_t()
        {
            reset();
        }

        address_t( const char* host, uint16_t port, int flag = 0 )
        {
            reset( host, port, flag );
        }

        address_t( const sockaddr* addr, std::size_t size )
        {
            reset( addr, size );
        }

        address_t( const address_t& addr )
        {
            reset( addr.ptr(), addr.len() );
        }

        address_t& operator=( const address_t& ins )
        {
            if( this != &ins ) reset( ins.ptr(), ins.len() );
            return *this;
        }

        std::string str() const
        {
            std::string s;
            getnameinfo( *this, s );
            return s;
        }

        std::size_t len() const
        {
            switch ( this->ss_family )
            {
            case AF_INET6: return _address_t< emV6 >::emSIZE;
            case AF_INET:  return _address_t< emV4 >::emSIZE;
            default: return emSIZE;
            }
        }

        std::size_t hash() const
        {
            hude::utils::hash_t< std::size_t > _hash;

            auto p = this->ptr_all();

            if( this->ss_family == _address_t< emV6 >::emSIZE )
            {
                auto as = (const uint32_t*)(const void*)&(p->sa6.sin6_addr);
                return _hash.hash( p->sa6.sin6_port, as[0], as[1], as[2], as[3] );
            } else {
                return _hash.hash( p->sa4.sin_port, p->sa4.sin_addr.s_addr );
            }
        }

        operator sockaddr*() { return (sockaddr*)this; }
        operator const sockaddr*() const { return (const sockaddr*)this; }

        sockaddr* ptr() { return (sockaddr*)this; }
        const sockaddr* ptr() const { return (sockaddr*)this; }

        sockaddr_all_t* ptr_all() { return (sockaddr_all_t*)this; }
        const sockaddr_all_t* ptr_all() const { return (sockaddr_all_t*)this; }
    };

    /*********************************************************************
     * @brief 比较两个地址
     */
    inline bool operator==( const address_t& a, const address_t& b )
    {
        if( a.ss_family != b.ss_family ) return false;
        auto siz = (a.ss_family == (uint16_t)AF_INET6 )?
            static_cast< std::size_t >( _address_t< emV6 >::emSIZE ) :
            static_cast< std::size_t >( _address_t< emV4 >::emSIZE );
        return memcmp( &a, &b, siz ) == 0;
    }
} //namespace dnet

namespace std
{
    /*********************************************************************
     * @brief hash_address_t 计算地址的HASH
     */
    template<>
    struct hash< dnet::address_t > { std::size_t operator()( const dnet::address_t& addr ) const { return addr.hash(); } };
} // namespace std

namespace dnet
{
    /*********************************************************************
     * @brief Socket选项管理
     */
    struct sockopts_t
    {
        enum : int { emLINGER_TIMEOUT = 60 };

        typedef std::size_t             size_recv_t;
        typedef linger                  linger_t;
        typedef struct{}                noblock_t;
        typedef struct{ int flag; }     reuse_addr_t;

        /*********************************************************************
         * @brief KeepAlive选项定义
         * @param keepalive     开启keepalive属性
         * @param keepidle      如该连接在keepidle秒内没有任何数据往来,则进行探测
         * @param keepinterval  探测时发包的时间间隔为keepinterval秒
         * @param keepcount     探测尝试的次数
         */
        struct keepalive_t
        {
            int keepalive;
            int keepidle;
            int keepinterval;
            int keepcount;
        };

        /*********************************************************************
         * @brief reuse addr选项设置
         * @param value     reuse addr选项
         * @return 返回0为正常， 非0错误
         */
        static int set_option( socket_t socket, reuse_addr_t value )
        {
            return _socket_setsockopt( socket, SOL_SOCKET, SO_REUSEADDR, &value.flag, sizeof( int ) );
        }

        /*********************************************************************
         * @brief KeepAlive选项设置
         * @param keepalive     keepalive_t选项
         * @return 返回0为正常， 非0错误
         */
        static int set_option( socket_t socket, const keepalive_t& ka )
        {
            int ret = 0;

            ret = _socket_setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, (void *)&ka.keepalive, sizeof(int));
            if( ret ) return ret;
            #ifdef TCP_KEEPIDLE
            ret = _socket_setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&ka.keepidle, sizeof(int));
            if( ret ) return ret;
            #endif
            #ifdef TCP_KEEPINTVL
            ret = _socket_setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&ka.keepinterval, sizeof(int));
            if( ret ) return ret;
            #endif
            #ifdef TCP_KEEPCNT
            ret = _socket_setsockopt(socket, IPPROTO_TCP, TCP_KEEPCNT, (void *)&ka.keepcount, sizeof(int));
            if( ret ) return ret;
            #endif

            return ret;
        }

        /*********************************************************************
         * @brief size_recv选项设置
         * @param n     size_recv_t选项
         * @return 返回0为正常， 非0错误
         */
        static int set_option( socket_t socket, size_recv_t n )
        {
            return _socket_setsockopt( socket, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n) );
        }

        /*********************************************************************
         * @brief linger选项设置
         * @param linger     优雅关闭选项
         * @return 返回0为正常， 非0错误
         * @details 
         *  1、设置 l_onoff为0，则该选项关闭，l_linger的值被忽略，等于内核缺省情况，close调用会立即返回给调用者，如果可能将会传输任何未发送的数据；
         *  2、设置 l_onoff为非0，l_linger为0，则套接口关闭时TCP夭折连接，TCP将丢弃保留在套接口发送缓冲区中的任何数据并发送一个RST给对方，而不是通常的四分组终止序列，这避免了TIME_WAIT状态；
         *  3、设置 l_onoff 为非0，l_linger为非0，当套接口关闭时内核将拖延一段时间（由l_linger决定）。如果套接口缓冲区中仍残留数据，进程将处于睡眠状态，直 到（a）所有数据发送完且被对方确认，之后进行正常的终止序列（描述字访问计数为0）或（b）延迟时间到。此种情况下，应用程序检查close的返回值是非常重要的，如果在数据发送完并被确认前时间到，close将返回EWOULDBLOCK错误且套接口发送缓冲区中的任何数据都丢失。close的成功返回仅告诉我们发送的数据（和FIN）已由对方TCP确认，它并不能告诉我们对方应用进程是否已读了数据。如果套接口设为非阻塞的，它将不等待close完成。
         *  注释：l_linger的单位依赖于实现: 4.4BSD假设其单位是时钟滴答（百分之一秒），但Posix.1g规定单位为秒。
         */
        static int set_option( socket_t socket, linger_t linger )
        {
            return _socket_setsockopt(socket, SOL_SOCKET, SO_LINGER, (const char *) &linger, sizeof(linger));
        }

        /*********************************************************************
         * @brief block选项设置
         * @param block  清除或者设置socket的阻塞位
         * @return 返回0为正常， 非0错误
         */
        static int set_option( socket_t socket, noblock_t block )
        {
            return _socket_set_non_block( socket );
        }

        /*********************************************************************
         * @brief socket选项设置
         * @param option 
         * @return 返回0为正常， 非0错误
         */
        template< typename _first >
        static int options( socket_t socket, _first&& option )
        {
            return set_option( socket, std::forward< _first >( option ) );
        }

        /*********************************************************************
         * @brief socket多选项设置
         * @param option 
         * @return 返回0为正常， 非0错误
         */
        template< typename _first, typename ... _args >
        static int options( socket_t socket, _first first, _args&& ... args )
        {
            int ret = set_option( socket, std::forward< _first >( first ) );
            if( ret ) return ret;

            return options( socket, std::forward< _args >( args ) ... );
        }
    };

    /*********************************************************************
     * @brief ...
     */
    template< std::size_t _count >
    using context_t = hude::aio::context_t< _count, hude::any_t >;

    /*********************************************************************
     * @brief 创建IO对象的智能指针
     */
    template <typename _type, typename _ctx, typename... _args>
    inline std::shared_ptr< _type > _io_obj( std::shared_ptr< _ctx > ctx, _args && ... args )
    {
        auto ret = std::shared_ptr< _type >( new _type( ctx, std::forward< _args >( args ) ... ) );
        
        return ret;
    }

    /*********************************************************************
     * @brief 创建IO对象的智能指针
     */
    template <typename _type, typename _ctx, typename... _args>
    inline std::shared_ptr< _type > io_obj( std::shared_ptr< _ctx > ctx, _args && ... args )
    {
        auto ret = _io_obj< _type >( ctx, std::forward< _args >( args ) ... );

        if( ret->state() ) ret->attach();
        
        return ret;
    }

    /*********************************************************************
     * @brief socket收发操作
     */
    template< std::size_t _count >
    struct _sock_t :
        public hude::aio::e2e::_peer_t,
        public std::enable_shared_from_this< _sock_t< _count > >
    {
        //----------------------------------------------------------------------
        using this_t   = _sock_t< _count >;
        using base_t   = hude::aio::e2e::_peer_t;
        using sock_t   = std::shared_ptr< _sock_t< _count > >;
        using ctx_t    = std::shared_ptr< context_t< _count > >;
        using on_evt_t = std::function< void( sock_t ) >;

        //----------------------------------------------------------------------
        ctx_t           ctx_;        //异步IO上下文
        socket_t        sock_;
        hude::any_t     user_;
        bool            attached_;

        //----------------------------------------------------------------------
        on_evt_t  on_recv_;
        on_evt_t  on_send_; 
        on_evt_t  on_close_;

        //----------------------------------------------------------------------
        virtual void _on_recv ( sock_t sock ) { if( on_recv_  ) on_recv_ ( sock ); }
        //----------------------------------------------------------------------
        virtual void _on_send ( sock_t sock ) { if( on_send_  ) on_send_ ( sock ); }
        //----------------------------------------------------------------------
        virtual void _on_close( sock_t sock ) { if( on_close_ ) on_close_( sock ); }

        //----------------------------------------------------------------------
        void set_on_recv( on_evt_t cb ) { on_recv_ = cb; }
        //----------------------------------------------------------------------
        void set_on_send( on_evt_t cb ) { on_send_ = cb; }
        //----------------------------------------------------------------------
        void set_on_close( on_evt_t cb ) { on_close_ = cb; }

        //----------------------------------------------------------------------
        _sock_t( ctx_t ctx, socket_t sock ) : ctx_( ctx ), sock_( sock ), attached_( false )
        {
            _log_tra( "<aio>", "\t _sock_t::_sock_t( %p )", this );

            on_send_ = [=]( sock_t ) { this->attach( event_t::emEPOLLET | event_t::emEPOLLIN ); };
        }

        //----------------------------------------------------------------------
        _sock_t( ctx_t ctx, int domain, int type, int protocol ) :
            _sock_t( ctx, _socket_open( domain, type, protocol ) )
        {
        }

        //----------------------------------------------------------------------
        ~_sock_t() override
        {
            _socket_shutdown( sock_, SHUTDOWN_RDWD );
            _socket_close( sock_ );

            _log_tra( "<aio>", "\t _sock_t::~_sock_t( %p )", this );
        }

        //----------------------------------------------------------------------
        _sock_t& operator=( socket_t sock )
        {
            return sock_ = sock, *this;
        }

        //----------------------------------------------------------------------
        typename base_t::handle_t native() const override
        {
            return sock_;
        }

        //----------------------------------------------------------------------
        socket_t operator*() const
        {
            return sock_;
        }

        //----------------------------------------------------------------------
        bool empty() const
        {
            return this->sock_ < 0;
        }

        //----------------------------------------------------------------------
        operator socket_t() const
        {
            return sock_;
        }

        //----------------------------------------------------------------------
        void close() override
        {
            this->detach();
        }

        //----------------------------------------------------------------------
        sock_t ptr() { return this->shared_from_this(); }

        //----------------------------------------------------------------------
        int recvfrom( void* ptr, size_t siz, address_t& addr, int flg = 0 )
        {
            socklen_t len = addr.len();

            auto ret = _socket_recvfrom( sock_, ptr, siz, flg, addr.ptr(), &len );

            if( siz && ( ret == 0 || ( ret < 0 && _socket_get_error() != EAGAIN ) ) )
            {
                _log_war( "<aio>", "\t --sock%d(%p)->recvfrom() == %d, detach()", **this, this, ret );

                this->detach();
            }

            return ret;
        }

        //----------------------------------------------------------------------
        int sendto( const void* ptr, size_t siz, address_t& addr, int flg = 0 )
        {
            auto ret = _socket_sendto( sock_, ptr, siz, flg, addr.ptr(), addr.len() );

            if( siz && ( ret == 0 || ( ret < 0 && _socket_get_error() != EAGAIN ) ) )
            {
                _log_war( "<aio>", "\t --sock%d(%p)->sendto() == %d, detach()", **this, this, ret );

                this->detach();
            }

            return ret;
        }

        //----------------------------------------------------------------------
        int recv( void* ptr, size_t siz, int flg )
        {
            auto ret = _socket_recv( sock_, ptr, siz, flg );

            if( siz && ( ret == 0 || ( ret < 0 && _socket_get_error() != EAGAIN ) ) )
            {
                _log_war( "<aio>", "\t --sock%d(%p)->recv() == %d, detach()", **this, this, ret );

                this->detach();
            }

            return ret;
        }

        //----------------------------------------------------------------------
        int send( const void* ptr, size_t siz, int flg )
        {
            auto ret = _socket_send( sock_, ptr, siz, flg );

            if( siz && ( ret == 0 || ( ret < 0 && _socket_get_error() != EAGAIN ) ) )
            {
                _log_war( "<aio>", "\t --sock%d(%p)->send() == %d, detach()", **this, this, ret );

                this->detach();
            }

            return ret;
        }

        //----------------------------------------------------------------------
        int recv( void* ptr, size_t siz ) override
        {
            return recv( ptr, siz, 0 );
        }

        //----------------------------------------------------------------------
        int send( const void* ptr, size_t siz ) override
        {
            return send( ptr, siz, 0 );
        }

        //----------------------------------------------------------------------
        template< size_t _size = 256U, typename _buffer >
        int recv( _buffer& buffer )
        {
            enum : size_t { emSIZ_STEP = _size };

            buffer.resize( emSIZ_STEP );

            auto ret = this->recv( &(buffer[0]), emSIZ_STEP );

            if( ret > 0 ) buffer.resize( ret );

            return ret;
        }

        //----------------------------------------------------------------------
        template< typename _buffer >
        int send( const _buffer& buffer )
        {
            return this->send( &(buffer[0]), buffer.size() );
        }

        //----------------------------------------------------------------------
        template< size_t _size = 256U, typename _buffer >
        int recv_all( _buffer& buffer )
        {
            int ret = 0;

            hude::buffers_t results;

            _buffer tmp;

            while( true )
            {
                ret = this->recv< _size >( tmp );

                if( ret > 0 )
                {
                    results.push_back( _buffer{} );
                    std::swap( tmp, results.back() );
                } else {
                    break;
                }
            }

            hude::move( buffer, results );
            
            return ret;
        }

        //----------------------------------------------------------------------
        template< typename _buffer >
        int send_all( const _buffer& buffer )
        {
            int ret = 0;

            const auto* b = &(buffer[0]);
            const auto* e = b + buffer.size();
            const auto* p = b;
    
            // 循环发送，直到没有数据
            while( p < e )
            {
                ret = this->send( p, e - p );
    
                if( ret < 0 ) {
                    // 发生错误
                    break;
                } else {
                    // 可能还有数据
                    p += ret;
                }
            }

            return ( ret == 0 )? 0 : p - b;
        }

        //----------------------------------------------------------------------
        int get_addr_local( address_t& addr )
        {
            addr.reset();
            socklen_t len = addr.len();
            return _socket_getsockname( **this, addr.ptr(), &len );
        }

        //----------------------------------------------------------------------
        int get_addr_peer( address_t& addr )
        {
            addr.reset();
            socklen_t len = addr.len();
            return _socket_getpeername( **this, addr.ptr(), &len );
        }

        //----------------------------------------------------------------------
        const char* error() const
        {
            static hude::format_t ret;
            const int& e = _socket_get_error();
            ret( "errno( %d ) %s", e, strerror( e ) );
            return ret.c_str();
        }

        //----------------------------------------------------------------------
        void on_event( uint32_t evt, sock_t sock )
        {
            if( evt & event_t::emEPOLLERR || evt & event_t::emEPOLLHUP )
            {
                log_inf( "\t --sock%d(%p)->event( %#x | emEPOLLERR )", **this, this, evt );

                this->detach();

                return;
            }

            if( evt == event_t::emEPOLLCLOSE )
            {
                _log_dug( "<aio>", "\t --sock%d(%p)->event( %#x | emEPOLLCLOSE )", **this, this, evt );

                this->detach();
            }

            if( evt & event_t::emEPOLLIN )
            {
                _log_dug( "<aio>", "\t --sock%d(%p)->event( %#x | emEPOLLIN )", **this, this, evt );

                _on_recv( sock );
            }

            if( evt & event_t::emEPOLLOUT )
            {
                _log_dug( "<aio>", "\t --sock%d(%p)->event( %#x | emEPOLLOUT )", **this, this, evt );

                _on_send( sock );
            }
        }

        //----------------------------------------------------------------------
        int attach( uint32_t evt = event_t::emEPOLLIN | event_t::emEPOLLOUT )
        {
            // 注册epoll事件处理，当事件发生时只是将事件处理加到任务池中，让任务池异步去处理
            auto cb = [=]( uint32_t evt, hude::any_t& user ) -> void
            {
                this->on_event( evt, hude::any_cast< sock_t >( user ) );
            };

            attached_ = true;

            auto ret = this->ctx_->evt_commit( **this, cb, this->ptr(), event_t::emEPOLLET | evt );

            _log_nte( "<aio>", "# (%p)->attach( sock: %d, evts: %#x )", this, **this, evt );

            return ret;
        }

        //----------------------------------------------------------------------
        int detach()
        {
            _log_nte( "<aio>", "# (%p)->detach( sock: %d )", this, **this );

            auto p = this->ptr();

            //if( ! attached_ ) return -100;

            auto ret = this->ctx_->evt_remove( **this );

            if( attached_ ) p->_on_close( this->ptr() );

            attached_ = false;

            return ret;
        }
    };

    /*********************************************************************
     * @brief ...
     */
    template< std::size_t _count >
    struct udp_vlink_t;

    /*********************************************************************
     * @brief UDP Bind模式下的虚拟链路
     */
    template< std::size_t _count >
    struct _vlink_t :
        public hude::aio::e2e::_peer_t,
        public std::enable_shared_from_this< _vlink_t< _count > >
    {
        //----------------------------------------------------------------------
        using this_t   = _vlink_t< _count >;
        using base_t   = hude::aio::e2e::_peer_t;
        using ctx_t    = std::shared_ptr< context_t< _count > >;
        using sock_t   = std::weak_ptr< udp_vlink_t< _count > >;
        using vlink_t  = std::shared_ptr< this_t >;
        using on_evt_t = std::function< void( vlink_t ) >;
        using queue_t  = hude::utils::block_queue_t< hude::buffer_t >;

        //----------------------------------------------------------------------
        ctx_t           ctx_;
        address_t       addr_;
        sock_t          sock_;
        queue_t         queue_;
        hude::any_t     user_;

        //----------------------------------------------------------------------
        on_evt_t    on_recv_;
        on_evt_t    on_send_; 
        on_evt_t    on_close_;

        //----------------------------------------------------------------------
        void set_on_recv( on_evt_t cb ) { on_recv_ = cb; }
        //----------------------------------------------------------------------
        void set_on_send( on_evt_t cb ) { on_send_ = cb; }
        //----------------------------------------------------------------------
        void set_on_close( on_evt_t cb ) { on_close_ = cb; }

        //----------------------------------------------------------------------
        _vlink_t( ctx_t ctx, const address_t& addr, std::shared_ptr< _sock_t< _count > > sock ) :
            ctx_( ctx ), addr_( addr ), sock_( std::dynamic_pointer_cast< udp_vlink_t< _count > >( sock ) )
        {
            _log_dug( "<aio>", "\t _vlink_t::_vlink_t( %p )", this );
        }

        //----------------------------------------------------------------------
        ~_vlink_t() override
        {
            _log_dug( "<aio>", "\t _vlink_t::~_vlink_t( %p )", this );
        }

        //----------------------------------------------------------------------
        vlink_t ptr() { return this->shared_from_this(); }

        //----------------------------------------------------------------------
        void close() override
        {
            auto self = this->shared_from_this();

            auto p = sock_.lock();
            p->attach_vlink( self );

            if( on_close_ ) on_close_( self );
        }

        //----------------------------------------------------------------------
        typename base_t::handle_t native() const override
        {
            return sock_.lock()->native();
        }

        //----------------------------------------------------------------------
        int recv( void* ptr, size_t siz, int flg )
        {
            if( queue_.empty() ) return -1;

            auto q = queue_t::freedom_t( &queue_ );

            auto& frame = q->front();

            if( siz < frame.size() )
            {
                memcpy( ptr, &(frame[0]), siz );

                hude::buffer_t tmp( frame.begin() + siz, frame.end() );
                std::swap( frame, tmp );
            } else {
                siz = frame.size();

                memcpy( ptr, &(frame[0]), siz );

                q->pop_front();
            }

            return siz;
        }

        //----------------------------------------------------------------------
        int send( const void* ptr, size_t siz, int flg )
        {
            auto p = sock_.lock();
            return ( sock_.expired() )? 0 : p->sendto( ptr, siz, addr_, flg );
        }

        //----------------------------------------------------------------------
        int recv( void* ptr, size_t siz ) override
        {
            return recv( ptr, siz, 0 );
        }

        //----------------------------------------------------------------------
        int send( const void* ptr, size_t siz ) override
        {
            return send( ptr, siz, 0 );
        }

        //----------------------------------------------------------------------
        template< typename _buffer >
        int recv( _buffer& buffer )
        {
            if( queue_.empty() ) return -1;

            auto q = queue_t::freedom_t( &queue_ );

            auto& frame = q->front();

            std::swap( frame, buffer );

            q->pop_front();

            return buffer.size();
        }

        //----------------------------------------------------------------------
        template< typename _buffer >
        int send( const _buffer& buffer )
        {
            int ret = 0;

            const auto* b = &(buffer[0]);
            const auto* e = b + buffer.size();
            const auto* p = b;
    
            // 循环发送，直到没有数据
            while( p < e )
            {
                ret = this->send( p, e - p );
    
                if( ret < 0 ) {
                    // 发生错误
                    break;
                } else {
                    // 可能还有数据
                    p += ret;
                }
            }

            return ( ret < 0 )? ret : p - b;
        }

        //----------------------------------------------------------------------
        int mult_cast( const void* ptr, size_t siz, const address_t& addr, int flg = 0 )
        {
            auto p = sock_.lock();
            return ( sock_.expired() )? 0 : p->sendto( ptr, siz, addr, flg );
        }
    };

    /*********************************************************************
     * @brief SOCKET通信服务基础
     */
    template< typename _sock, std::size_t _count >
    struct _service_base_t : public  _sock
    {
        //----------------------------------------------------------------------
        enum : std::size_t { emCOUNT = _count };

        //----------------------------------------------------------------------
        using this_t    = _service_base_t< _sock, _count >;
        using base_t    = _sock;

        using ctx_t     = typename base_t::ctx_t;
        using sock_t    = typename base_t::sock_t;
        using on_evt_t  = typename base_t::on_evt_t;

        //----------------------------------------------------------------------
        address_t   addr_;
        bool        state_;

        //----------------------------------------------------------------------
        _service_base_t( ctx_t ctx, socket_t sock, const address_t& addr ) :
            base_t( ctx, sock ), addr_( addr ), state_( false )
        {
            sockopts_t::options( **this, sockopts_t::noblock_t{}, sockopts_t::linger_t{ 1, sockopts_t::emLINGER_TIMEOUT } );
        }

        //----------------------------------------------------------------------
        _service_base_t( ctx_t ctx, socket_t sock, const char* host, uint16_t port ) :
            _service_base_t( ctx, sock, address_t{ host, port } )
        {
        }

        //----------------------------------------------------------------------
        ~_service_base_t()
        {
        }

        //----------------------------------------------------------------------
        bool state() const { return state_; }

        //----------------------------------------------------------------------
        void state( bool s ) { state_ = s;  }
    };

    /*********************************************************************
     * @brief SOCKET通信服务基础的别名
     */
    template< std::size_t _count >
    using _service_t = _service_base_t< _sock_t< _count >, _count >;

    /*********************************************************************
     * @brief TCP端口监听
     */
    template< std::size_t _count >
    struct tcp_listen_t :
        public  _service_t< _count >
    {
        //----------------------------------------------------------------------
        enum : std::size_t { emDEFAULT_BACKLOG = ( (_count / 500U) < 2U )? 2U : (_count / 500U) };

        //----------------------------------------------------------------------
        using this_t    = tcp_listen_t< _count >;
        using base_t    = _service_t< _count >;

        using ctx_t     = typename base_t::ctx_t;
        using sock_t    = typename base_t::sock_t;
        using on_evt_t  = typename base_t::on_evt_t;

        using client_t  = _service_t< _count >;

        using accept_t  = std::function< void( const address_t&, sock_t ) >;

        //----------------------------------------------------------------------
        accept_t   accept_;  //响应接入请求

        //----------------------------------------------------------------------
        tcp_listen_t( ctx_t ctx, const address_t& addr, accept_t accept, std::size_t backlog = emDEFAULT_BACKLOG ) :
            base_t( ctx, _socket_open( addr.ss_family, SOCK_STREAM, 0 ), addr ), accept_( accept )
        {
            this->state_ = this->boot( backlog );
        }

        //----------------------------------------------------------------------
        tcp_listen_t( ctx_t ctx, const char* host, uint16_t port, accept_t accept, std::size_t backlog = emDEFAULT_BACKLOG ) :
            tcp_listen_t( ctx, address_t( host, port, AI_PASSIVE ), accept, backlog ) //, AI_PASSIVE | AI_NUMERICHOST
        {
        }

        //----------------------------------------------------------------------
        ~tcp_listen_t()
        {
        }

        //----------------------------------------------------------------------
        // 如果有就绪的连接请求，在线程池内异步创建对应的客户socket对象，触发请求事件，最后加入epoll事件监听
        void _on_recv( sock_t sock ) override
        {
            while( true )
            {
                address_t addr;
                socklen_t size = sizeof( address_t );

                auto skt = _socket_accept( **this, addr.ptr(), &size );
                if( skt < 0 ) return;

                _log_dug( "<aio>", "\t --sock%d(%p)->accept( %d )", **this, this, skt );

                auto ret = sockopts_t::options( skt,
                    sockopts_t::noblock_t{},
                    sockopts_t::linger_t{ 1, sockopts_t::emLINGER_TIMEOUT },
                    sockopts_t::keepalive_t{ 1, 15, 15, 3 }
                );

                if( ! ret )
                {
                    auto client = _io_obj< client_t >( this->ctx_, skt, addr );

                    accept_( addr, std::static_pointer_cast< _sock_t< _count > >( client ) );

                    client->attach();
                }
            }
        }

        //----------------------------------------------------------------------
        bool boot( std::size_t backlog )
        {
            {
                auto ret = sockopts_t::options( **this, sockopts_t::reuse_addr_t{ 1 } );
                if( ret ) return false;
            }

            if( this->empty() || ! this->ctx_ ) return false;

            {
                auto ret = _socket_bind( **this, this->addr_.ptr(), this->addr_.len() );
                if( ret ) return false;
            }

            {
                auto ret = _socket_listen( **this, backlog );
                if( ret ) return false;
            }

            {
                auto ret = sockopts_t::options( **this, sockopts_t::noblock_t{} );

                if( ret ) return false;
            }

            return true;
        }
    };

    /*********************************************************************
     * @brief TCP连接
     */
    template< std::size_t _count >
    struct tcp_connect_t :
        public  _service_t< _count >
    {
        //----------------------------------------------------------------------
        using this_t    = tcp_connect_t< _count >;
        using base_t    = _service_t< _count >;

        using ctx_t     = typename base_t::ctx_t;
        using sock_t    = typename base_t::sock_t;
        using on_evt_t  = typename base_t::on_evt_t;

        //----------------------------------------------------------------------
        tcp_connect_t( ctx_t ctx, const address_t& addr, on_evt_t ready ) :
            base_t( ctx, _socket_open( addr.ss_family, SOCK_STREAM, 0 ), addr )
        {
            if( ready )
            {
                this->on_send_ = [=]( sock_t sock )
                {
                    this->attach( event_t::emEPOLLET | event_t::emEPOLLIN );
                    ready( sock );
                };
            } else {
                log_war( "net tcp_connect_t( %p )::ready == empty", this );
            }

            this->state_ = boot();
        }

        //----------------------------------------------------------------------
        tcp_connect_t( ctx_t ctx, const char* host, uint16_t port, on_evt_t ready ) :
            tcp_connect_t( ctx, address_t( host, port ), ready )
        {
        }

        //----------------------------------------------------------------------
        ~tcp_connect_t()
        {
        }

        //----------------------------------------------------------------------
        bool boot()
        {
            {
                auto ret = sockopts_t::options( **this, sockopts_t::reuse_addr_t{ 1 } );
                if( ret ) return false;
            }

            {
                auto ret = _socket_connect( **this, this->addr_.ptr(), this->addr_.len() );
                if( ret && _socket_get_error() != ERR_SOCK_WAITTING ) return false;
                // if( ret == 0 && this->on_send_ ) this->on_send_( this->shared_from_this );
            }

            {
                auto ret = sockopts_t::options( **this,
                    sockopts_t::noblock_t{},
                    sockopts_t::linger_t{ 1, sockopts_t::emLINGER_TIMEOUT },
                    sockopts_t::keepalive_t{ 1, 15, 15, 3 }
                );

                if( ret ) return false;
            }

            return true;
        }
    };

    /*********************************************************************
     * @brief UDP端口绑定
     */
    template< std::size_t _count >
    struct udp_bind_t :
        public  _service_t< _count >
    {
        //----------------------------------------------------------------------
        using this_t    = udp_bind_t< _count >;
        using base_t    = _service_t< _count >;

        using ctx_t     = typename base_t::ctx_t;
        using sock_t    = typename base_t::sock_t;
        using on_evt_t  = typename base_t::on_evt_t;

        //----------------------------------------------------------------------
        udp_bind_t( ctx_t ctx, const address_t& addr, on_evt_t ready ) :
            base_t( ctx, _socket_open( addr.ss_family, SOCK_DGRAM, 0 ), addr )
        {
            if( ready )
            {
                this->on_send_ = [=]( sock_t sock )
                {
                    this->attach( event_t::emEPOLLET | event_t::emEPOLLIN );
                    ready( sock );
                };
            } else {
                log_war( "net udp_bind_t( %p )::ready == empty", this );
            }

            this->state_ = boot();
        }

        //----------------------------------------------------------------------
        udp_bind_t( ctx_t ctx, const char* host, uint16_t port, on_evt_t ready ) :
            udp_bind_t( ctx, address_t( host, port ), ready )
        {
        }

        //----------------------------------------------------------------------
        ~udp_bind_t()
        {
        }

        //----------------------------------------------------------------------
        bool boot()
        {
            {
                auto ret = sockopts_t::options( **this, sockopts_t::reuse_addr_t{ 1 } );
                if( ret ) return false;
            }

            {
                auto ret = _socket_bind( **this, (const sockaddr*)&(this->addr_), this->addr_.len() );
                if( ret ) return false;
            }

            {
                auto ret = sockopts_t::options( **this,
                    sockopts_t::noblock_t{},
                    sockopts_t::linger_t{ 1, sockopts_t::emLINGER_TIMEOUT }
                );

                if( ret ) return false;
            }

            return true;
        }
    };

    /*********************************************************************
     * @brief UDP连接
     */
    template< std::size_t _count >
    struct udp_connect_t :
        public  _service_t< _count >
    {
        //----------------------------------------------------------------------
        using this_t    = udp_connect_t< _count >;
        using base_t    = _service_t< _count >;

        using ctx_t     = typename base_t::ctx_t;
        using sock_t    = typename base_t::sock_t;
        using on_evt_t  = typename base_t::on_evt_t;

        //----------------------------------------------------------------------
        udp_connect_t( ctx_t ctx, const address_t& addr, on_evt_t ready ) :
            base_t( ctx, _socket_open( addr.ss_family, SOCK_DGRAM, 0 ), addr )
        {
            if( ready )
            {
                this->on_send_ = [=]( sock_t sock )
                {
                    this->attach( event_t::emEPOLLET | event_t::emEPOLLIN );
                    ready( sock );
                };
            } else {
                log_war( "net udp_connect_t( %p )::ready == empty", this );
            }

            this->state_ = boot();
        }

        //----------------------------------------------------------------------
        udp_connect_t( ctx_t ctx, const char* host, uint16_t port, on_evt_t ready ) :
            udp_connect_t( ctx, address_t( host, port ), ready )
        {
        }

        //----------------------------------------------------------------------
        ~udp_connect_t()
        {
        }

        //----------------------------------------------------------------------
        bool boot()
        {
            {
                auto ret = sockopts_t::options( **this, sockopts_t::reuse_addr_t{ 1 } );
                if( ret ) return false;
            }

            {
                auto ret = _socket_connect( **this, this->addr_.ptr(), this->addr_.len() );
                if( ret && _socket_get_error() != EINPROGRESS ) return false;
            }

            {
                auto ret = sockopts_t::options( **this,
                    sockopts_t::noblock_t{},
                    sockopts_t::linger_t{ 1, sockopts_t::emLINGER_TIMEOUT }
                );

                if( ret ) return false;
            }

            return true;
        }
    };

    /*********************************************************************
     * @brief UDP端口虚拟链路
     */
    template< std::size_t _count >
    struct udp_vlink_t :
        public  _service_t< _count >
    {
        //----------------------------------------------------------------------
        using this_t    = udp_vlink_t< _count >;
        using base_t    = _service_t< _count >;
        using ctx_t     = typename base_t::ctx_t;
        using sock_t    = typename base_t::sock_t;
        using vlink_t   = std::shared_ptr< _vlink_t< _count > >;
        using links_t   = std::unordered_map< address_t, vlink_t >;
        using accept_t  = std::function< void( const address_t&, vlink_t ) >;

        //----------------------------------------------------------------------
        accept_t   accept_;  //响应接入请求
        links_t    links_;
        std::mutex mutex_;

        //----------------------------------------------------------------------
        udp_vlink_t( ctx_t ctx, const address_t& addr, accept_t accepted ) :
            base_t( ctx, _socket_open( addr.ss_family, SOCK_DGRAM, 0 ), addr ), accept_( accepted )
        {
            this->state_ = boot();
        }

        //----------------------------------------------------------------------
        udp_vlink_t( ctx_t ctx, const char* host, uint16_t port, accept_t accepted ) :
            udp_vlink_t( ctx, address_t( host, port ), accepted )
        {
        }

        //----------------------------------------------------------------------
        ~udp_vlink_t()
        {
        }

        //----------------------------------------------------------------------
        bool boot()
        {
            {
                auto ret = sockopts_t::options( **this, sockopts_t::reuse_addr_t{ 1 } );
                if( ret ) return false;
            }

            {
                auto ret = _socket_bind( **this, this->addr_.ptr(), this->addr_.len() );
                if( ret ) return false;
            }

            {
                auto ret = sockopts_t::options( **this,
                    sockopts_t::noblock_t{},
                    sockopts_t::linger_t{ 1, sockopts_t::emLINGER_TIMEOUT }
                );

                if( ret ) return false;
            }

            return true;
        }

        //----------------------------------------------------------------------
        // socket关闭事件递归传递到所有虚拟通道
        void _on_close( sock_t sock ) override
        {
            links_t tmp;

            {
                std::lock_guard< std::mutex > _al( mutex_ );

                std::swap( tmp, links_ );
            }

            for( auto i : tmp )
            {
                auto link = i.second;

                if( link->on_close_ ) link->on_close_( link );
            }

            base_t::_on_close( sock );
        }

        //----------------------------------------------------------------------
        // 当有UDP可读事件时，读取数据及来源，根据来源转发到对应虚拟链路的接收缓存
        void _on_recv( sock_t sock ) override
        {
            int ret = 0;

            while( true )
            {
                enum : std::size_t { emSIZE = 1024U };
                hude::buffer_t buffer( emSIZE );

                address_t addr;

                {
                    ret = sock->recvfrom( &(buffer[0]), emSIZE, addr, 0 );
                    if( ret <= 0 ) return;

                    buffer.resize( ret );
                }

                typename links_t::iterator itr;

                // 如果是新主机来源建立对应虚拟链路
                {
                    std::lock_guard< std::mutex > _al( mutex_ );

                    itr = this->links_.find( addr );

                    if( itr == this->links_.end() )
                    {
                        auto ret = this->links_.emplace( addr, new _vlink_t< _count >{ this->ctx_, addr, sock } );

                        itr = ret.first;

                        accept_( addr, itr->second );
                    }
                }

                auto vlink = itr->second;

                // 将数据放入对应虚拟链路的数据队列中
                {
                    auto g = typename hude::utils::block_queue_t< hude::buffer_t >::producter_t{ &(vlink->queue_) }; 

                    g->push_back( hude::buffer_t{} );

                    std::swap( g->back(), buffer );
                }

                // 将接收事件转发到对应虚拟链路
                {
                    if( vlink->on_recv_ )
                    {
                        vlink->on_recv_( vlink );
                    }
                }
            }
        }

        //----------------------------------------------------------------------
        void attach_vlink( vlink_t link )
        {
            std::lock_guard< std::mutex > _al( mutex_ );

            links_.erase( link->addr_ );
        }
    };

    /*********************************************************************
     * @brief 服务的相关类型粹取器
     */
    template< typename _service, std::size_t _count = 0U >
    struct net_traits_t {};

    template< std::size_t _count >
    struct net_traits_t< tcp_listen_t< _count > >
    {
        enum : std::size_t { emCOUNT = _count };
        using type_t        = tcp_listen_t< _count >; 
        using raw_channel_t = _sock_t< _count >;
        using ptr_channel_t = std::shared_ptr< _sock_t< _count > >;
    };

    template< std::size_t _count >
    struct net_traits_t< tcp_connect_t< _count > >
    {
        enum : std::size_t { emCOUNT = _count };
        using type_t        = tcp_connect_t< _count >; 
        using raw_channel_t = _sock_t< _count >;
        using ptr_channel_t = std::shared_ptr< _sock_t< _count > >;
    };

    template< std::size_t _count >
    struct net_traits_t< udp_bind_t< _count > >
    {
        enum : std::size_t { emCOUNT = _count };
        using type_t        = udp_bind_t< _count >; 
        using raw_channel_t = _sock_t< _count >;
        using ptr_channel_t = std::shared_ptr< _sock_t< _count > >;
    };

    template< std::size_t _count >
    struct net_traits_t< udp_connect_t< _count > >
    {
        enum : std::size_t { emCOUNT = _count };
        using type_t        = udp_connect_t< _count >; 
        using raw_channel_t = _sock_t< _count >;
        using ptr_channel_t = std::shared_ptr< _sock_t< _count > >;
    };

    template< std::size_t _count >
    struct net_traits_t< udp_vlink_t< _count > >
    {
        enum : std::size_t { emCOUNT = _count };
        using type_t        = udp_vlink_t< _count >; 
        using raw_channel_t = _vlink_t< _count >;
        using ptr_channel_t = std::shared_ptr< _vlink_t< _count > >;
    };

} //dnet

/*********************************************************************
 * @brief 状态流程ID定义
 */
namespace hude
{
    namespace net
    {
        /*********************************************************************
         * @brief 导出裸类型
         */

        //----------------------------------------------------------------------
        using address_t     = dnet::address_t;

        //----------------------------------------------------------------------
        template< std::size_t _count >
        using context_t     = dnet::context_t< _count >;

        //----------------------------------------------------------------------
        template< std::size_t _count >
        using _sock_t       = dnet::_sock_t< _count >;

        //----------------------------------------------------------------------
        template< std::size_t _count >
        using _vlink_t      = dnet::_vlink_t< _count >;

        //----------------------------------------------------------------------
        template< std::size_t _count >
        using tcp_listen_t  = dnet::tcp_listen_t< _count >;

        //----------------------------------------------------------------------
        template< std::size_t _count >
        using tcp_connect_t = dnet::tcp_connect_t< _count >;

        //----------------------------------------------------------------------
        template< std::size_t _count >
        using udp_bind_t    = dnet::udp_bind_t< _count >;

        //----------------------------------------------------------------------
        template< std::size_t _count >
        using udp_connect_t = dnet::udp_connect_t< _count >;

        //----------------------------------------------------------------------
        template< std::size_t _count >
        using udp_vlink_t   = dnet::udp_vlink_t< _count >;

        //----------------------------------------------------------------------
        template< typename _service >
        using net_traits_t  = dnet::net_traits_t< _service >; 

        /*********************************************************************
         * @brief 导出网络工具集
         */
        template< std::size_t _count = hude::aio::emDEFAULT_MAX_EPOLL >
        struct net_t
        {
            //----------------------------------------------------------------------
            enum { emMAX_CONNECTED = _count };

            //----------------------------------------------------------------------
            using address_t     = dnet::address_t;
            using context_t     = dnet::context_t< _count >;
            using _sock_t       = dnet::_sock_t< _count >;
            using _vlink_t      = dnet::_vlink_t< _count >;

            //----------------------------------------------------------------------
            using tcp_listen_t  = dnet::tcp_listen_t< _count >;
            using tcp_connect_t = dnet::tcp_connect_t< _count >;
            using udp_bind_t    = dnet::udp_bind_t< _count >;
            using udp_connect_t = dnet::udp_connect_t< _count >;
            using udp_vlink_t   = dnet::udp_vlink_t< _count >;

            //----------------------------------------------------------------------
            using service_t     = std::shared_ptr< dnet::_service_t< _count > >;
            using aio_t         = std::shared_ptr< dnet::context_t< _count > >;
            using ctx_t         = std::shared_ptr< dnet::context_t< _count > >;
            using sock_t        = std::shared_ptr< dnet::_sock_t< _count > >;
            using vlink_t       = std::shared_ptr< dnet::_vlink_t< _count > >;
            using ref_sock_t    = std::weak_ptr< dnet::_sock_t< _count > >;
            using ref_vlink_t   = std::weak_ptr< dnet::_vlink_t< _count > >;

            //----------------------------------------------------------------------
            template <typename _type, typename... _args>
            static inline std::shared_ptr< _type > io_obj( ctx_t ctx, _args && ... args )
            {
                auto ret = dnet::_io_obj< _type >( ctx, std::forward< _args >( args ) ... );

                ret->attach();
                
                return ret;
            }
        };

    } //namespace net
} //namespace hude

#endif //__network_kenny_ojfwoeeif9w23__

